#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include <ESP8266mDNS.h>

#define DEBUG //是否开启debug功能

#ifdef DEBUG
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
#else
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    
#define DebugPrintln(message)    
#define DebugPrint(message)    
#endif
 
const char* AP_SSID     = "TP-LINK_5344";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* AP_PSK = "6206908you11011010";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码
const unsigned long BAUD_RATE = 9600;                   // serial connection speed

const char HTML_HEADER[] PROGMEM = R"EOF(<!DOCTYPE html><html><head><meta http-equiv='refresh' content='5'/><meta charset="UTF-8"></meta><title>基于物联网的防火警报系统</title>)EOF";
const char HTML_STYLE[] PROGMEM = R"EOF(<style>.space{margin-left: 10px;height: 30px;line-height: 30px;width: 88px;font-size: 15px;text-align: center;color: #FFFFFF;background-color: #0c727e;border-radius: 4px;}.space:hover{transform: scale(1.03);cursor: pointer;}</style></head>)EOF";
const char HTML_SCRIPT[] PROGMEM = R"EOF(<script type="text/javascript">var xmlhttp;if(window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}else{xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}function openAlarm(){xmlhttp.open("GET","/Warn?t=on",true);xmlhttp.send();}function closeAlarm(){xmlhttp.open("GET","/Warn?t=off",true);xmlhttp.send();}function normalAlarm(){xmlhttp.open("GET","/Warn?t=on1",true);xmlhttp.send();}</script>)EOF";  
const char HTML_BODY1[] PROGMEM = R"EOF(<body style="background-color: #FFFFFF;"><h2 align="center" style="color: #0C727E;font-size: 40px;font-family: " 楷体";">基于物联网的防火警报系统&nbsp;&nbsp;<span style="font-size: 20px;color: #75DC66;font-family: " 微软雅黑";">(当前状态: {s})</span></h2>)EOF";
const char HTML_BODY2[] PROGMEM = R"EOF(<h3 align="center" style="color: lightblue;font-size: 25px;font-family: " 微软雅黑";">温度:&nbsp;{t}<span style="font-size: 25px;color: lightblue;font-family: " 微软雅黑";">&nbsp;&nbsp;&nbsp;湿度:&nbsp;{h}</span></h3><h3 align="center" style="color: lightblue;font-size: 25px;font-family: " 微软雅黑";">气体浓度:&nbsp;{f}</h3>)EOF";
const char HTML_BODY3[] PROGMEM = R"EOF(<table align="center"><tr><td style="color: #625A33;font-size: 20px;font-family: "黑体";">警报控制:</td><td><button type="button" class="space" onclick="openAlarm()">&nbsp;开&nbsp;</button></td><td><button type="button" class="space" onclick="closeAlarm()">&nbsp;关&nbsp;</button></td></tr></table><table align="center"><tr><td style="color: #625A33;font-size: 20px;font-family: "黑体";">启动正常警报:</td><td><button type="button" class="space" onclick="normalAlarm()">&nbsp;开&nbsp;</button></td><td><button type="button" class="space" onclick="closeAlarm()">&nbsp;关&nbsp;</button></td></tr></table></body></html>)EOF";  
 
//声明一下函数
void initBasic(void);
void initWifi(void);
void initWebServer(void);
void initmDNS(void);


int temp = 0; // 温度
int humidity = 0;  // 湿度
int mqval = 0; // 气体浓度
int msg = 0; // 状态
char res[50];

 
ESP8266WebServer server(80);
 
/**
 * 处理根目录uri请求
 * uri:http://server_ip/
 */
void handleRoot() {
  DebugPrintln("handleRoot");

  String page = FPSTR(HTML_HEADER);
  page += FPSTR(HTML_STYLE);
  page += FPSTR(HTML_SCRIPT);
  page += FPSTR(HTML_BODY1);
  if (msg == 1){
    page.replace("{s}","温度过高");
  } else if(msg == 2){
    page.replace("{s}","有明火危险");
  } else if(msg == 3){
    page.replace("{s}","气体浓度过高");
  } else {
    page.replace("{s}","正常");
  }
  
  page += FPSTR(HTML_BODY2);
  page.replace("{t}",String(temp));
  page.replace("{h}",String(humidity));
  page.replace("{f}",String(mqval));
  page += FPSTR(HTML_BODY3);
 
  server.sendHeader("Content-Length", String(page.length()));
  server.send(200, "text/html", page);        
}
 
/**
 * 处理无效uri
 * uri:http://server_ip/xxxx
 */
void handleNotFound() {
  DebugPrintln("handleNotFound");
  //打印无效uri的信息 包括请求方式 请求参数
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

/**
 * 处理警报控制
 */
void handleWarn() {
  DebugPrintln("handleWarn");
  //打印无效uri的信息 包括请求方式 请求参数
  StaticJsonBuffer<50> jsonBuffer;
  //创建最外层的json对象 —— root对象，顶节点
  JsonObject& root = jsonBuffer.createObject();
  //给最外层json对象添加属性
  root["t"] = server.arg(0);
  //在串口中打印，prettyPrintTo方法会格式化json
  root.printTo(Serial);
}
 
void setup(void) {
  initBasic();
  initWifi();
  initWebServer();
  initmDNS();
}
 
void loop(void) {
  MDNS.update();
  // 处理web请求
  server.handleClient();
  
  if(Serial.available()>0){
      // {"t":30,"h":50,"m":40,"s":0}
      DebugPrintln("insert data");
      memset(res, 0, 50);      //清空
      int length = Serial.readBytesUntil('}',res, 50);
      while(Serial.available()>0){
        char c = Serial.read();
      }
     
      DebugPrintln(length);
      res[length] = '}';
      res[++length] = 0;
      DebugPrintln(res);
      
      DynamicJsonBuffer jsonBuffer;
      JsonObject& root = jsonBuffer.parseObject(res);

      // 解析数据
      if (!root.success()) {
        DebugPrintln("JSON parsing failed!");
      } else {
         DebugPrintln("JSON parsing success!");
         // 更新数据
         if (root.containsKey("t")){
            temp = root["t"]; //温度
         }

         if (root.containsKey("h")){
            humidity = root["h"]; //湿度
         }

         if (root.containsKey("m")){
            mqval = root["m"]; //气体浓度
         }

         if (root.containsKey("s")){
            msg = root["s"]; //状态
         }
      }
   }

  // 喂狗
  ESP.wdtFeed();
}
 
/**
 * 初始化基础功能：波特率
 */
void initBasic(){
  // 初始化波特率
  DebugBegin(BAUD_RATE);
  Serial.begin(BAUD_RATE);
  // 使能看门狗
  ESP.wdtEnable(5000);
}
 
/**
 * 初始化wifi模块：工作模式 连接网络
 */
void initWifi(){
  // 设置STA工作模式
  WiFi.mode(WIFI_STA);
  // 连接WiFi热点
  WiFi.begin(AP_SSID, AP_PSK);
  DebugPrintln("");
 
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
  DebugPrint("Connected to ");
  DebugPrintln(AP_SSID);
  // 打印IP地址
  DebugPrint("IP address: ");
  DebugPrintln(WiFi.localIP());
}
 
/**
 * 初始化webserver
 */
void initWebServer(){
  //以下配置uri对应的handler
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.on("/Warn", handleWarn);
  //启动webserver
  server.begin();
  DebugPrintln("HTTP server started");
}

/**
 * 初始化mDNS
 */
void initmDNS(){
  if (!MDNS.begin("esp8266")) {
    DebugPrintln("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  DebugPrintln("mDNS responder started,please input http://esp8266.local/ in your browser after install Bonjour");
}
